﻿/***********************************************************************************************
 * 
 * ProjectName: WMSSoft.WinKStart.DataSource
 * 
 * Description: Provides a DataSource for User defined DataItems
 * 
 * Created:     27.07.2014
 * 
 * Author:      matthias wagler - matthias@WMSSoft.de
 * 
 * Copyright:   Copyright 2014 by WMSSoft.de
 * 
 * License:     GPLv3
 * 
 * History:     27.07.2014 - matthias wagler matthias@WMSSoft.de   -   Created
 * 
 **********************************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WMSSoft.Lib.Basic;
using WMSSoft.Lib.Enums;
using WMSSoft.Lib.Interfaces;
using WMSSoft.Lib.WinKStart;

namespace WMSSoft.WinKStart.DataSource
{
    public class UserDataSource : iWinKStartDataSource
    {
        #region Members
        private string _Name = "";
        private string _Assembly = "";
        private string _ClassName = "";
        private string _ShortName = "";
        private long _LastUpdated = 0;
        private bool _Searchable = false;
        private int _Priority = 0;
        private iWinKStartItem _Data = null;
        private List<iWinKStartItem> _Items = null;
        private Dictionary<string, KeyValueAssignment> m_Assignment = null;
        private Dictionary<string, KeyValueAssignment> m_Options = null;
        #endregion

        public event EventHandler LoadCompleted;

        public UserDataSource()
        {
            //Nothing TODO
        }

        #region Properties
        /// <summary>
        /// Contains the Name for this DataSet to access it from panels
        /// </summary>
        public string Name
        {
            get { return _Name; }
            set { _Name = value; }
        }

        /// <summary>
        /// Contains the Assembly Filename to load from
        /// </summary>
        public string AssemblyName
        {
            get { return _Assembly; }
            set { _Assembly = value; }
        }

        /// <summary>
        /// Contains the ClassName to run code
        /// </summary>
        public string ClassName
        {
            get { return _ClassName; }
            set { _ClassName = value; }
        }

        /// <summary>
        /// Contains the Name to view in settings page if the datasource
        /// is searchable
        /// </summary>
        public string ShortName
        {
            get { return _ShortName; }
            set { _ShortName = value; }
        }

        public long LastUpdated
        {
            get { return _LastUpdated; }
        }

        /// <summary>
        /// If true the DataSource is viewed in settingspage to select for searching
        /// </summary>
        public bool Searchable
        {
            get { return _Searchable; }
            set { _Searchable = value; }
        }

        /// <summary>
        /// Contains the Priority to load this DataSource when other Datasources are available
        /// </summary>
        public int Priority
        {
            get { return _Priority; }
            set { _Priority = value; }
        }

        /// <summary>
        /// Contains the loaded Data
        /// </summary>
        public iWinKStartItem Data
        {
            get { return _Data; }
            set { _Data = value; }
        }

        /// <summary>
        /// Contains all user defined DataItems
        /// </summary>
        public List<iWinKStartItem> Items
        {
            get { return _Items; }
            set { _Items = value; }
        }

        /// <summary>
        /// Contains a set of assignments to configure the behavior
        /// </summary>
        public Dictionary<string, KeyValueAssignment> Assignments
        {
            get { return m_Assignment; }
            set { m_Assignment = value; }
        }

        /// <summary>
        /// Contains a set of Configuration - Options for this Source
        /// </summary>
        public Dictionary<string, KeyValueAssignment> Options
        {
            get { return m_Options; }
            set { m_Options = value; }
        }

        #endregion

        #region Public Methods

        public bool Init()
        {
            try
            {
                if (_Data == null)
                {
                    _Data = new cStartmenuItem(_Name + "_ROOT", "RootItem", eLinkExecutionTypes.Program, "", eExecutionProcedure.Unknown,
                                                eItemType.Root, "", null, null, "", "", "", "");
                    ApplyUserDatItems();

                    _LastUpdated = DateTime.Today.Ticks;

                    //fire event
                    DoLoadCompleted();
                    return true;
                }
                else
                    return false;
            }
            catch (Exception Ex)
            {
                return false;
            }
        }

        public bool UnloadDataSource()
        {
            //Nothing todo
            return true;
        }

        public bool AddItem(iWinKStartItem Item, string ParentKey)
        {
            try
            {
                if (_Data != null)
                {
                    if (ParentKey.Length == 0)
                    {

                        if (_Data.ChildItems.ContainsKey(Item.ItemName) == false)
                        {
                            _Data.AddChild(Item);
                            //fire event
                            DoLoadCompleted();
                            return true;
                        }
                        else return false;
                    }
                    else
                    {
                        //split parent key 
                        string[] ParentKeys = ParentKey.Split('\\');
                        bool bParentExist = true;
                        cStartmenuItem CurrentParent = (cStartmenuItem)_Data;

                        foreach (string KeyItem in ParentKeys)
                        {
                            if (CurrentParent.ChildItems.ContainsKey(KeyItem) == true)
                                CurrentParent = (cStartmenuItem)CurrentParent.ChildItems[KeyItem];
                            else
                            {
                                bParentExist = false;
                                break;
                            }
                        }

                        if (bParentExist == true)
                        {
                            CurrentParent.AddChild(Item);
                            //fire event
                            DoLoadCompleted();
                            return true;
                        }
                        else return false;
                    }
                }
                else return false;
                
            }
            catch (Exception Ex)
            {
                throw new Exception("Can't add Item!", Ex);
            }
        }

        public bool AddChilds(Dictionary<string, object> Childs, string ParentKey)
        {
            try
            {
                if (_Data != null)
                {
                    if (ParentKey.Length == 0)
                    {
                        _Data.AddChilds(Childs);
                        //fire event
                        DoLoadCompleted();
                        return true;
                    }
                    else
                    {
                        //split parent key 
                        string[] ParentKeys = ParentKey.Split('\\');
                        bool bParentExist = true;
                        cStartmenuItem CurrentParent = (cStartmenuItem)_Data;

                        foreach (string KeyItem in ParentKeys)
                        {
                            if (CurrentParent.ChildItems.ContainsKey(KeyItem) == true)
                                CurrentParent = (cStartmenuItem)CurrentParent.ChildItems[KeyItem];
                            else
                            {
                                bParentExist = false;
                                break;
                            }
                        }

                        if (bParentExist == true)
                        {
                            CurrentParent.AddChilds(Childs);
                            //fire event
                            DoLoadCompleted();
                            return true;
                        }
                        else return false;
                    }
                }
                else
                    return false;
            }
            catch (Exception Ex)
            {
                throw new Exception("Can't add Childs!", Ex);
            }
        }

        public bool DeleteItem(string ItemKey, string ParentKey)
        {
            try
            {
                if (ParentKey.Length == 0)
                {
                    if (_Data.ChildItems.ContainsKey(ItemKey) == true)
                    {
                        _Data.RemoveChild(ItemKey);
                        //fire event
                        DoLoadCompleted();
                        return true;
                    }
                    else return false;
                }
                else
                {
                    string[] ParentKeys = ParentKey.Split('\\');
                    bool bParentExist = true;
                    cStartmenuItem CurrentParent = (cStartmenuItem)_Data;

                    foreach (string KeyItem in ParentKeys)
                    {
                        if (CurrentParent.ChildItems.ContainsKey(KeyItem) == true)
                            CurrentParent = (cStartmenuItem)CurrentParent.ChildItems[KeyItem];
                        else
                        {
                            bParentExist = false;
                            break;
                        }
                    }

                    if (bParentExist == true)
                    {
                        if (CurrentParent.ChildItems.ContainsKey(ItemKey) == true)
                        {
                            CurrentParent.RemoveChild(ItemKey);
                            //fire event
                            DoLoadCompleted();
                            return true;
                        }
                        else return false;

                    }
                    else return false;
                }               
            }
            catch (Exception Ex)
            {
                throw new Exception("Can't remove Item!", Ex);
            }
        }

        public void ClearItems(string ParentKey)
        {
            try
            {
                if (ParentKey.Length >= 0)
                {
                    string[] ParentKeys = ParentKey.Split('\\');
                    bool bParentExist = true;
                    cStartmenuItem CurrentParent = (cStartmenuItem)_Data;

                    foreach (string KeyItem in ParentKeys)
                    {
                        if (CurrentParent.ChildItems.ContainsKey(KeyItem) == true)
                            CurrentParent = (cStartmenuItem)CurrentParent.ChildItems[KeyItem];
                        else
                        {
                            bParentExist = false;
                            break;
                        }
                    }

                    if (bParentExist == true)
                    {
                        CurrentParent.Clear();
                        //fire event
                        DoLoadCompleted();
                    }

                }
                else throw new Exception("No Parent Key given!");
            }
            catch (Exception Ex)
            {
                throw new Exception("can't clear Child for Parent '" + ParentKey + "'!", Ex);
            }
        }

        #endregion

        #region Private Methods
        void ApplyUserDatItems()
        {
            try
            {
                if (_Items != null && _Items.Count > 0)
                {
                    foreach (iWinKStartItem Item in _Items)
                    {
                        if (Item.Filter.Length > 0)
                        {
                            if (_Data.ChildItems.ContainsKey(Item.Filter.ToUpper()) == false)
                                _Data.AddChild(CreateFilterNode(Item.Filter));

                            if (_Data.ChildItems.ContainsKey(Item.Filter.ToUpper()) == true)
                            {
                                if (((cStartmenuItem)_Data.ChildItems[Item.Filter.ToUpper()]).ChildItems.ContainsKey(Item.ItemName) == false)
                                {
                                    ((cStartmenuItem)_Data.ChildItems[Item.Filter.ToUpper()]).AddChild(Item);
                                }
                            }
                        }
                        else
                        {
                            //add DataItem direct to the rootitem
                            if (_Data.ChildItems.ContainsKey(Item.ItemName.ToUpper()) == false)
                            {
                                _Data.AddChild(Item);
                            }
                        }
                    }
                }
            }
            catch (Exception Ex)
            {
                CMessagelogging.AppendMessage("Can't apply user dataitems!", Ex, EMessageTypes.Error);
            }
        }

        iWinKStartItem CreateFilterNode(string FilterName)
        {
            try
            {
                return new cStartmenuItem(FilterName.ToUpper(), FilterName, eLinkExecutionTypes.Program, "", eExecutionProcedure.Unknown,
                                          eItemType.Root, "", null, null, "", "", "", "");
            }
            catch (Exception Ex)
            {
                throw new Exception("Can't create Filter!", Ex);
            }
        }

        void DoLoadCompleted()
        {
            //fire event
            if (LoadCompleted != null) LoadCompleted(this, EventArgs.Empty);
        }
        #endregion
    }
}
